package main

import (
	"time"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

type Note struct {
	ID          uint      `gorm:"primaryKey;column:id" json:"id"`
	Abbreviated string    `json:"abbreviated"`
	Content     string    `json:"content"`
	CreateTime  time.Time `json:"createTime"`
	Tags        []Tag     `gorm:"many2many:note_tag;" json:"tags"`
}

func (Note) TableName() string {
	return "note"
}

type HeatMap struct {
	Date  string `json:"date"`
	Count uint   `json:"count"`
}

func InitDataSource() error {
	dataSource := globalConfig.DBPath

	dataSource = GetAbsPath(dataSource)

	var err error
	db, err = gorm.Open(sqlite.Open(dataSource), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		return err
	}

	db.AutoMigrate(&Note{}, &Tag{}, &NoteTag{})

	return nil
}

// Tag represents the tag table
type Tag struct {
	ID   uint   `gorm:"primaryKey" json:"id"`
	Name string `gorm:"unique;not null" json:"name"`
}

func (Tag) TableName() string {
	return "tag"
}

// NoteTag represents the data_tag join table
type NoteTag struct {
	NoteID uint `gorm:"primaryKey"`
	TagID  uint `gorm:"primaryKey"`
}

func (NoteTag) TableName() string {
	return "note_tag"
}

func SaveTag(tx *gorm.DB, note Note) error {
	if note.Tags == nil {
		return nil
	}

	var err error
	noteTags := make([]NoteTag, 0)
	for i := range note.Tags {
		err = tx.FirstOrCreate(&note.Tags[i], "name = ?", note.Tags[i].Name).Error
		if err != nil {
			return err
		}
		noteTags = append(noteTags, NoteTag{
			NoteID: note.ID,
			TagID:  note.Tags[i].ID,
		})
	}

	err = tx.Delete(&NoteTag{}, "note_id = ?", note.ID).Error
	if err != nil {
		return err
	}

	if len(noteTags) == 0 {
		return nil
	}
	err = tx.Create(&noteTags).Error
	if err != nil {
		return err
	}

	return nil
}
